<script setup lang="ts">
import {ref, watch} from "vue";

// 定义选项的类型
type SelectItem = {
  value: string | number;
  label: string;
  check: boolean;
}

// 定义 props 传入的参数
let props = defineProps({
  options: {
    type: Array<SelectItem>,
    required: true,
  },
  width: {
    type: Number,
    default() {
      return 220;  // 默认宽度为 220px
    }
  },
  bindValue: {
    type: Array<string | number>,
    default() {
      return []
    }
  }
});

// 根据传入的宽度设置下拉框的样式
let selectWidth = "width:" + props.width + "px";

// 定义触发事件的方法
const emit = defineEmits(["selected"]);

// 选中的项，存储选中的 value 值
let selectedOptions = ref<Array<string | number>>([]);

// 处理选中状态变化
const isChecked = (item: SelectItem) => {
  if (item.check && selectedOptions.value.indexOf(item.value) === -1) {
    // 如果选项被选中，并且 selectedOptions 中没有该项的值，则添加它
    selectedOptions.value.push(item.value);
  } else if (!item.check) {
    // 如果选项被取消选中，则从 selectedOptions 中移除该项
    selectedOptions.value.forEach((elm, idx) => {
      if (elm === item.value) {
        selectedOptions.value.splice(idx, 1);
      }
    });
  }
  // 触发 'selected' 事件，通知父组件更新选中的项
  emit('selected', selectedOptions.value);
};

// 移除标签
const removeTag = (value: any) => {
  // 遍历 options，根据值移除对应的项
  props.options.forEach((elm) => {
    if (elm.value === value) {
      elm.check = false;  // 取消选中状态
    }
  });
  // 触发选中事件，更新选中的项
  emit('selected', selectedOptions.value);
};

// 处理全选或反选功能
const selectAll = (isAll: boolean) => {
  if (isAll) {
    // 全选
    selectedOptions.value = [];  // 清空选中的项
    props.options.forEach((item: SelectItem) => {
      item.check = true;  // 设置每项为选中
      selectedOptions.value.push(item.value);  // 将选中的项的 value 添加到 selectedOptions
    });
    console.log(selectedOptions.value);  // 打印选中的项
  } else {
    // 反选
    let arr: Array<string | number> = [];  // 用于存储反选后的项
    props.options.forEach((item) => {
      item.check = false;  // 取消选中
      if (!selectedOptions.value.includes(item.value)) {
        item.check = true;  // 设置每项为选中
        arr.push(item.value);  // 如果该项未被选中，则添加到 arr
      }
    });
    selectedOptions.value = arr;  // 更新 selectedOptions

  }
  emit("selected", selectedOptions.value);  // 触发事件，通知父组件
};

// 清空下拉的数据
const clear = () => {
  selectedOptions.value = [];
}

// 暴露给父组件
defineExpose({clear})

//watch监听
watch(() => props.bindValue,
    (newValue) => {
      // 设置当前用户拥有的项
      selectedOptions.value = props.bindValue
      // 设置checkbox为选中
      props.bindValue.forEach(item => {
        props.options.find(dom => {
          if (dom.value === item) {
            dom.check = true
          }
        })
      })
    },
    {
      immediate: true
    }
)
</script>

<template>
  <!-- 下拉框加多选框 -->
  <el-select
      v-model="selectedOptions"
      multiple
      placeholder="请选择"
      popper-append-to-body="false"
      :style="selectWidth"
      @remove-tag="removeTag"
  >
    <!-- 遍历 options 渲染每个选项 -->
    <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item.value"
    >
      <el-checkbox v-model="item.check" @change="isChecked(item)">
        {{ item.label }}
      </el-checkbox>
    </el-option>

    <!-- 全选和反选操作 -->
    <div class="is-all">
      <div @click="selectAll(true)">全选</div>
      <div @click="selectAll(false)">反选</div>
    </div>
  </el-select>
</template>

<style scoped lang="scss">
.is-all {
  display: flex;
  padding-left: 10px;

  div {
    cursor: pointer;
    margin: 6px 10px;
    transition: 0.2s;

    &.hover {
      opacity: 0.7;
    }
  }
}
</style>
